-- 74HC595功能测试
-- 2021.05.07
-- Lingd
-- 福州泰诚网络科技有限公司
module(...,package.seeall)

require"pins"
require"bit"

-- 初始化状态
Data = {0xFC,0xFF,0xFF,0x00}                -- 开启背光，关闭指示灯、关闭继电器  

-- 闪烁变量
LedStatus = {{0,0},{0,0},{0,0},{0,0}}

-- 全局变量
LED_RED     = 1
LED_GREEN   = 2
DEV_4G      = 1
DEV_SYS     = 2
DEV_TCP     = 3

-- 引脚定义
local GPIO_595_CLK = pins.setup(pio.P0_12, 1)      -- 时钟
local GPIO_595_DAT = pins.setup(pio.P0_11, 1)      -- 数据
local GPIO_595_RCK = pins.setup(pio.P0_9,  1)      -- 锁存
local GPIO_595_OE  = pins.setup(pio.P0_10, 1)      -- 使能

-- 595发送一个字节
local function Send595Dat(Dat)

    local i = 0

    for i = 0,7 do
        GPIO_595_CLK(0)
        if bit.band(bit.rshift(Dat,i),0x01) == 0x00 then
            GPIO_595_DAT(0)
        else
            GPIO_595_DAT(1)
        end
        GPIO_595_CLK(1)
    end  
end

-- 595发送4个字节
function Send595Bytes(Data)
    local i = 1
    for i = 1,#Data do
        Send595Dat(Data[i])
    end
    GPIO_595_RCK(0)
    GPIO_595_RCK(1)
end

-- 开启红色指示灯 （CH：1~8）
-- 开启红灯的同时，需要关闭同路的绿灯
function LED_ChargeRedOn(ch)
    if ch > 4 then
        Data[2] = bit.clear(Data[2],(8-ch)*2+1)         -- 开启红灯
        Data[2] = bit.set(Data[2],(8-ch)*2)             -- 关闭同路绿灯
    else
        Data[3] = bit.clear(Data[3],(4-ch)*2+1)         -- 开启红灯灯
        Data[3] = bit.set(Data[3],(4-ch)*2)             -- 关闭同路绿灯
    end
    Send595Bytes(Data)
end

-- 开启绿色指示灯 （CH：1~8）
-- 开启绿灯的同时，需要关闭同路的红灯
function LED_ChargeGreenOn(ch)
    if ch > 4 then
        Data[2] = bit.clear(Data[2],(8-ch)*2)           -- 开启绿灯
        Data[2] = bit.set(Data[2],(8-ch)*2+1)           -- 关闭同路红灯
    else
        Data[3] = bit.clear(Data[3],(4-ch)*2)           -- 开启绿灯
        Data[3] = bit.set(Data[3],(4-ch)*2+1)           -- 关闭同路红灯
    end
    Send595Bytes(Data)
end

-- 根据通道状态恢复红色指示灯
function LED_ChargeRec(data)
    local i = 1

    for i = 0,7 do
        if bit.band(bit.rshift(bit.bnot(data),i*2),0x0003) > 0 then
            if i > 3 then
                Data[3] = bit.clear(Data[3],(i-4)*2+1)
            else
                Data[2] = bit.clear(Data[2],i*2+1)
            end
        end
    end

    Send595Bytes(Data)
end

-- 关闭指示灯 （CH：1~8）
function LED_ChargeOff(ch)
    if ch > 4 then
        Data[2] = bit.bor(Data[2],bit.rshift(0xC0,(ch-5)*2))
    else
        Data[3] = bit.bor(Data[3],bit.rshift(0xC0,(ch-1)*2))
    end
    Send595Bytes(Data)
end

-- 关闭所有指示灯
function LED_ChargeOff_All()
    Data[2] = 0xFF
    Data[3] = 0xFF
    Send595Bytes(Data)
end

-- 开启背光灯
function LED_BackOn()
    Data[1] = bit.band(Data[1],bit.bnot(0x03))
    Send595Bytes(Data)
end

-- 关闭背光灯
function LED_BackOff()
    Data[1] = bit.bor(Data[1],0x03)
    Send595Bytes(Data)
end

-- 4G信号指示灯
function LED_4G(state)
    if state > 0 and state < 4 then
        if state == 1 then                      -- 无信号：灭
            Data[1] = bit.bor(Data[1],0xC0)
        elseif state == 2 then                  -- 信号弱：红
            Data[1] = bit.bor(bit.band(Data[1],bit.bnot(0x80)),0x40)
        else                                    -- 信号正常：绿
            Data[1] = bit.bor(bit.band(Data[1],bit.bnot(0x40)),0x80)
        end
        Send595Bytes(Data)
        sys.timerStopAll(LED_4G_Twinkle)
    end
end

-- 4G指示灯闪烁（mode 1:红灯 2：绿灯 ontime：亮的时间ms offtime：灭的时间ms）
function LED_4G_Twinkle(ontime,offtime)
    if LedStatus[1][1] == 1 then
        LED_4G(1)                      -- 关闭
        sys.timerStart(LED_4G_Twinkle,offtime,ontime,offtime)
    else
        LED_4G(LedStatus[1][2]+1)      -- 亮灯
        sys.timerStart(LED_4G_Twinkle,ontime,ontime,offtime)
    end
    LedStatus[1][1] = 1 - LedStatus[1][1]
end

-- 系统状态指示灯
function LED_SYS(state)
    if state > 0 and state < 4 then
        if state == 1 then                      -- 灭
            Data[1] = bit.bor(Data[1],0x30)
        elseif state == 2 then                  -- 异常：红
            Data[1] = bit.bor(bit.band(Data[1],bit.bnot(0x20)),0x10)
        else                                    -- 正常：绿
            Data[1] = bit.bor(bit.band(Data[1],bit.bnot(0x10)),0x20)
        end
        Send595Bytes(Data)
        sys.timerStopAll(LED_SYS_Twinkle)
    end
end

-- 系统指示灯闪烁（ontime：亮的时间ms offtime：灭的时间ms）
function LED_SYS_Twinkle(ontime,offtime)
    if LedStatus[2][1] == 1 then
        LED_SYS(1)                      -- 关闭
        sys.timerStart(LED_SYS_Twinkle,offtime,ontime,offtime)
    else
        LED_SYS(LedStatus[2][2]+1)      -- 亮灯
        sys.timerStart(LED_SYS_Twinkle,ontime,ontime,offtime)
    end
    LedStatus[2][1] = 1 - LedStatus[2][1]
end

-- TCP连接指示灯
function LED_TCP(state)
    if state > 0 and state < 4 then
        if state == 1 then                      -- 无信号：灭
            Data[1] = bit.bor(Data[1],0x0C)
        elseif state == 2 then                  -- 信号弱：红
            Data[1] = bit.bor(bit.band(Data[1],bit.bnot(0x08)),0x04)
        else                                    -- 信号正常：绿
            Data[1] = bit.bor(bit.band(Data[1],bit.bnot(0x04)),0x08)
        end
        Send595Bytes(Data)
        sys.timerStopAll(LED_TCP_Twinkle)
    end
end

-- TCP指示灯闪烁（mode 1:红灯 2：绿灯 ontime：亮的时间ms offtime：灭的时间ms）
function LED_TCP_Twinkle(ontime,offtime)
    if LedStatus[3][1] == 1 then
        LED_TCP(1)                      -- 关闭
        sys.timerStart(LED_TCP_Twinkle,offtime,ontime,offtime)
    else
        LED_TCP(LedStatus[3][2]+1)      -- 亮灯
        sys.timerStart(LED_TCP_Twinkle,ontime,ontime,offtime)
    end
    LedStatus[3][1] = 1 - LedStatus[3][1]
end

-- LED闪烁控制（ch 1：4G指示灯 2：TCP指示灯 3：系统指示灯 mode 1:红灯 2：绿灯 ontime：亮的时间ms offtime：灭的时间ms）
function LED_Show(ch,mode,ontime,offtime)
    if ch == 1 then                             -- 4G指示灯
        LedStatus[1][1] = 0
        LedStatus[1][2] = mode
        sys.timerStopAll(LED_4G_Twinkle)
        LED_4G_Twinkle(ontime,offtime)
    elseif ch == 2 then                         -- 系统指示灯
        LedStatus[2][1] = 0
        LedStatus[2][2] = mode
        sys.timerStopAll(LED_SYS_Twinkle)
        LED_SYS_Twinkle(ontime,offtime) 
    else                                        --  TCP指示灯                   
        LedStatus[3][1] = 0
        LedStatus[3][2] = mode
        sys.timerStopAll(LED_TCP_Twinkle)
        LED_TCP_Twinkle(ontime,offtime)
    end
end

-- 开启继电器 （CH：1~8）
function K_On(ch)
    Data[4] = bit.bor(Data[4],bit.rshift(0x80,ch-1))
    Send595Bytes(Data)
end

-- 关闭继电器 （CH：1~8）
function K_Off(ch)
    Data[4] = bit.band(Data[4],bit.bnot(bit.rshift(0x80,ch-1)))
    Send595Bytes(Data)
end

-- 开启全部继电器
function K_On_All()
    Data[4] = 0xFF
    Send595Bytes(Data)
end

-- 恢复继电器状态
function K_On_Rec(data)
    Data[4] = data
    Send595Bytes(Data)
end

-- 关闭全部继电器 
function K_Off_All()
    Data[4] = 0x00
    Send595Bytes(Data)
end

sys.taskInit(function()
    Send595Bytes(Data)
    GPIO_595_OE(0)
end)